/*
 * @Author: ZhanXie
 * @Date: 2020-01-30 21:42:38
 * @LastEditors: ZhanXie
 * @LastEditTime: 2020-03-16 18:07:42
 * @Description: 项目 interface 定义
 * @FilePath: /projectStudy/ts-axios/src/types/index.ts
 */
// 方法类型 字符串类型别名
export type Method =
  | 'get'
  | 'GET'
  | 'delete'
  | 'DELETE'
  | 'head'
  | 'HEAD'
  | 'options'
  | 'OPTIONS'
  | 'post'
  | 'POST'
  | 'put'
  | 'PUT'
  | 'patch'
  | 'PATCH'

// 请求数据
export interface AxiosRequestConfig {
  url?: string
  method?: Method
  data?: any
  params?: any
  headers?: any
  responseType?: XMLHttpRequestResponseType
  timeout?: number
  transformRequest?: AxiosTransformer | AxiosTransformer[]
  transformResponse?: AxiosTransformer | AxiosTransformer[]
  cancelToken?: CancelToken // 取消请求
  withCredentials?: Boolean // 跨域携带 cookie
  xsrfCookieName?: string // XSRF 防御
  xsrfHeaderName?: string // XSRF 防御
  username?: string // HTTP 授权
  password?: string // HTTP 授权
  onDownloadProgress?: (e: ProgressEvent) => void // 下载进度监控
  onUploadProgress?: (e: ProgressEvent) => void // 上传进度监控
  validateStatus?: (status: number) => boolean // 自定义合法状态码
  paramsSerializer?: (params: any) => string // 自定义参数序列化
  baseURL?: string // 一旦配置了 `baseURL`，之后请求传入的 `url` 都会和我们的 `baseURL` 拼接成完整的绝对地址，除非请求传入的 `url` 已经是绝对地址

  [propName: string]: any
}

// 响应数据
export interface AxiosResponse<T = any> {
  data: T
  status: number
  statusText: string
  headers: any
  config: AxiosRequestConfig
  request: any
}

// 错误数据
export interface AxiosError extends Error {
  config: AxiosRequestConfig
  code?: string
  request?: any
  response?: AxiosResponse
  isAxiosError: boolean
}

// Axios 对象接口
export interface Axios {
  request<T = any>(config: AxiosRequestConfig): AxiosPromise<T>
  get<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
  delete<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
  head<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
  options<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
  post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>
  put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>
  patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>

  getUri(config?: AxiosRequestConfig): string
}

/**
 * axios 实例接口
 * 混合借口
 * 函数重载
 */
export interface AxiosInstance extends Axios {
  <T = any>(config: AxiosRequestConfig): AxiosPromise<T>
  <T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
}

export interface AxiosClassStatic {
  new (config: AxiosRequestConfig): Axios
}

export interface AxiosStatic extends AxiosInstance {
  create(config?: AxiosRequestConfig): AxiosInstance

  CancelToken: CancelTokenStatic
  Cancel: CancelStatic
  isCancel: (value: any) => boolean

  all<T>(promises: Array<T | Promise<T>>): Promise<T[]>
  spread<T, R>(callback: (...args: T[]) => R): (arr: T[]) => R
  Axios: AxiosClassStatic
}

export interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {}

export interface ResolvedFn<T> {
  (val: T): T | Promise<T>
}

export interface RejectedFn {
  (error: any): any
}

// 拦截器管理接口
export interface AxiosInterceptorManager<T> {
  use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number
  eject(id: number): void
}

export interface AxiosTransformer {
  (data: any, headers: any): any
}

// 实例类型的接口定义
export interface CancelToken {
  promise: Promise<Cancel>
  reason?: Cancel

  throwIfRequested(): void
}

// 取消方法的接口定义
export interface Canceler {
  (message?: string): void
}

// CancelExecutor` 是 `CancelToken` 类构造函数参数的接口定义
export interface CancelExecutor {
  (cancel: Canceler): void
}

// CancelToken 扩展静态接口
export interface CancelTokenSource {
  token: CancelToken
  cancel: Canceler
}

// CancelToken 类的类类型
export interface CancelTokenStatic {
  new (executor: CancelExecutor): CancelToken
  source(): CancelTokenSource
}

// 实例类型的接口定义
export interface Cancel {
  message?: string
}

// 类类型的接口定义
export interface CancelStatic {
  new (message?: string): Cancel
}
